import os

from flask import Flask, request, send_file
from flask_restx import Resource, Api, reqparse, fields
import json
from flask_sqlalchemy import SQLAlchemy

from dao.EventDao import EventDao

app = Flask(__name__)
# 配置文档展开
# app.config.SWAGGER_UI_DOC_EXPANSION = 'full'
api = Api(app)
# 数据库地址配置
app.config["SQLALCHEMY_DATABASE_URI"] = f"sqlite:///{os.path.abspath('db/main.db')}"
db = SQLAlchemy()
db.init_app(app)
# 数据库操作类
eventDao = EventDao(db)

# 定义请求数据模型
my_model = api.model('MyModel', {
    "name": fields.String(description="The name of the event", required=True),
    "date": fields.String(description="The date of the event (in DD-MM-YYYY format)", required=True),
    "from": fields.String(description="The start time of the event (in HH:MM:SS format)", required=True),
    "to": fields.String(description="The end time of the event (in HH:MM:SS format)", required=True),
    "location": fields.String(description="The location of the event ", required=True),
    # "location": fields.Nested({
    #     "street": fields.String(description="The street name"),
    #     "suburb": fields.String(description="The suburb name"),
    #     "state": fields.String(description="The state abbreviation (e.g. NSW)"),
    #     "post-code": fields.String(description="The post code")
    # }),
    "description": fields.String(description="A description of the event")
})

event_model = api.model('Event', {
    'from': fields.String(required=True, description='The start time of the event in HH:MM:SS format'),
    'to': fields.String(required=True, description='The end time of the event in HH:MM:SS format'),
    'description': fields.String(description='Optional. A description of the event')
})


# 创建数据
@api.route("/events", methods=['POST', 'GET'])
class EventsHandler1(Resource):
    @api.doc(responses={200: 'Events returned successfully', 400: 'Invalid input'},
             params={
                 'order': {'type': 'string',
                           'description': 'The order in which to return events (e.g. "+id" or "-name")',
                           'default': '+id'},
                 'page': {'type': 'integer', 'description': 'The page number to return', 'default': 1},
                 'size': {'type': 'integer', 'description': 'The number of events to return per page', 'default': 10},
                 'filter': {'type': 'string',
                            'description': 'The fields to include in each event object (comma-separated)',
                            'default': 'id,name'}
             })
    def get(self):
        """
        Get a list of events.
        Parameters:
            order (str): The order in which to return events (e.g. "+id" or "-name"). Default is "+id".
            page (int): The page number to return. Default is 1.
            size (int): The number of events to return per page. Default is 10.
            filter (str): The fields to include in each event object (comma-separated). Default is "id,name".
        """
        # 获取JSON传递过来的数据
        parser = reqparse.RequestParser()
        parser.add_argument('order')
        parser.add_argument('page')
        parser.add_argument('size')
        parser.add_argument('filter')
        args = parser.parse_args()
        if not args.get('order'):
            args['order'] = '+id'
            pass
        if not args.get('page'):
            args['page'] = 1
            pass
        if not args.get('size'):
            args['size'] = 10
            pass
        if not args.get('filter'):
            args['filter'] = 'id,name'
            pass

        # 解析JSON转成字典数据
        result = eventDao.filter(args)
        if result.get('code') == 200:
            return result.get('data'), 200
        else:
            return {"message": result.get('message')}, 400
        pass

    @api.doc(responses={201: 'Event created successfully', 400: 'Invalid input'})
    @api.expect(my_model)
    def post(self):
        """
        Create a new event.

        Request Body:
        {
            "name": "my birthday paty",
            "date": "02-01-2020",
            "from": "13:09:00",
            "to": "13:08:00",
            "location": {
                "street": "2158 Night Ave",
                "suburb": "Kensington",
                "state": "NSW",
                "post-code": "2033"
            },
            "description": "some notes on the vent"
        }
        """
        # 获取JSON传递过来的数据
        data = request.get_data()
        # 解析JSON转成字典数据
        json_data = json.loads(data.decode("UTF-8"))
        result = eventDao.create(json_data)
        if result.get('code') == 200:
            return result.get('data'), 201
        else:
            return {"message": result.get('message')}, 400
        pass


# 查询数据
@api.route("/events/<int:id>", methods=['GET', 'DELETE', 'PATCH'])
class EventsHandler2(Resource):
    def get(self, id):
        result = eventDao.get(id)
        if result:
            return result, 200
        else:
            return {"message": "data created fail"}, 400
        pass

    def delete(self, id):
        result = eventDao.delete(id)
        if result.get('code') == 200:
            return result.get('data'), 201
        else:
            return {"message": result.get('message')}, 400
        pass

    @api.expect(event_model)
    def patch(self, id):
        """
        Update an event by ID.

        Parameters:
            id (int): The ID of the event to update.

        Request Body:
            from (str): The start time of the event in HH:MM:SS format.
            to (str): The end time of the event in HH:MM:SS format.
            description (str): Optional. A description of the event.

        Returns:
            dict: A dictionary containing the updated event data.
        """
        # 获取JSON传递过来的数据
        data = request.get_data()
        # 解析JSON转成字典数据
        json_data = json.loads(data.decode("UTF-8"))

        result = eventDao.update(id, data=json_data)
        if result.get('code') == 200:
            return result.get('data'), 200
        else:
            return {"message": result.get('message')}, 400
        pass


# 统计数据
@api.route("/events/statistics", methods=['GET'])
class EventsHandler3(Resource):

    @api.doc(params={
        'format': 'Optional. The response format. If set to "image", returns a PNG image of the statistics chart.'
    })
    def get(self):
        """
        Returns statistics for events.
        Parameters:
            format (str): Optional. The response format. If set to 'image', returns a PNG image of the statistics chart.
        Returns:
            dict or file: A dictionary containing the statistics data, or a PNG image file if format is set to 'image'.
        """
        parser = reqparse.RequestParser()
        parser.add_argument('format', type=str)
        args = parser.parse_args()
        print(args)
        result = eventDao.statistics(data=args)
        if result.get('code') == 200:
            if args.format == 'image':
                return send_file(result.get("data"), mimetype='image/png')
            else:
                return result.get('data'), 200
        else:
            return {"message": result.get('message')}, 400
        pass


if __name__ == '__main__':
    app.run()
